home *** CD-ROM | disk | FTP | other *** search
- /*
- * On a clear disk you can seek forever...
- *
- * Clear out all unused blocks on a disk, and if a whole track is
- * unused, delete the appropriate track file.
- *
- * $Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $
- * $Log: xdclear.c,v $
- * Revision 1.3 1995/04/08 20:23:48 Rhialto
- * Add/correct version strings.
- *
- * Revision 1.2 1995/04/02 14:58:51 Rhialto
- * Take LowCyl into account. This fixes partitions that don't start at cyl 0.
- * Change ETD_* commands to TD_* because the A4000's scsi.device does not
- * understand them.
- * Fix bogus exit status.
- *
- * Revision 1.1 1993/11/08 13:23:03 Rhialto
- * Initial revision
- *
- * (C) Copyright 1993,1995 by Olaf 'Rhialto' Seibert. All rights reserved.
- */
-
- #include "xpkdisk.h"
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <dos/dos.h>
- #include <dos/filehandler.h>
-
- extern struct DosLibrary *DOSBase;
- extern struct ExecBase *SysBase;
-
- static const char idString[] = "\0$VER: xdClear " STR(VERSION) "." STR(REVISION) "\r\n";
- static const char rcsId[] = "$Id: xdclear.c,v 1.3 1995/04/08 20:23:48 Rhialto Exp $";
-
- struct FileSysStartupMsg Fssm;
- struct DosEnvec De;
- struct IOExtTD *Io;
- struct MsgPort *Port;
- struct MsgPort *HandlerPort;
- ULONG NumTracks;
- ULONG MaxKey;
- ULONG RootBlockKey;
- ULONG *RootBlock;
- ULONG BitsPerBitmapBlock;
- ULONG BMBlocksPerBitmapExtBlock;
- ULONG BitmapBlockNr = -2;
- ULONG *BitmapBlock;
- ULONG BitmapExtBlockNr = -1;
- ULONG *BitmapExtBlock;
- ULONG *ZeroBlock;
- ULONG LowTrack;
- ULONG Offset;
- int XpkDisk;
- int Pretend;
- int Verbose;
-
- int SectorsCleared;
- int SectorsReallyCleared;
- int TracksDeleted;
- int TracksReallyDeleted;
-
- #define debug(x) printf x
- #define debug0(x)
-
- #define SIZE De.de_SizeBlock
-
- #define BM_BLOCKS_PER_ROOTBLOCK ((-25)-(-49)+1)
- #define BM_BLOCKS_PER_BMEBLOCK (SIZE - 1)
-
- int
- GetKey(ULONG key, ULONG *buffer)
- {
- long offset = Offset + sizeof(ULONG) * SIZE * key;
-
- Io->iotd_Req.io_Command = CMD_READ; /* ETD */
- Io->iotd_Req.io_Offset = offset;
- Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
- Io->iotd_Req.io_Data = (char *)buffer;
-
- if (DoIO((struct IORequest *)Io)) {
- printf("Read error %d on sector %d (offset 0x%lx bytes, %dK, %dM)!\n",
- Io->iotd_Req.io_Error, key, offset, offset / 1024, offset / (1024 * 1024));
- if (Verbose) {
- printf("device=\"%s\" unit %d\n", Fssm.fssm_Device, Fssm.fssm_Unit);
- }
- return Io->iotd_Req.io_Error;
- }
- return 0;
- }
-
- int
- PutKey(ULONG key, ULONG *buffer)
- {
- Io->iotd_Req.io_Command = CMD_WRITE; /* ETD */
- Io->iotd_Req.io_Offset = Offset + sizeof(ULONG) * SIZE * key;
- Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
- Io->iotd_Req.io_Data = (char *)buffer;
-
- if (DoIO((struct IORequest *)Io)) {
- printf("Write error %d on sector %d!\n",
- Io->iotd_Req.io_Error, key);
- return Io->iotd_Req.io_Error;
- }
- return 0;
- }
-
- /*
- * All checksums make the block add to 0.
- */
- int
- CheckSum(ULONG *buffer)
- {
- int i;
- ULONG sum = 0;
-
- for (i = SIZE; i > 0; i--)
- sum += *buffer++;
-
- return sum? 0 : 1;
- }
-
- int
- GetBitmapExtBlock(ULONG blocknr)
- {
- if (blocknr != BitmapExtBlockNr) {
- ULONG key;
- ULONG keynr;
-
- if (blocknr < BitmapExtBlockNr || BitmapExtBlockNr == (ULONG)-1) {
- key = RootBlock[SIZE - 24];
- keynr = 0;
- if (Verbose >= 2)
- printf("GetBitmapExtBlock %d -> first key %d\n", blocknr, key);
- } else {
- key = BitmapExtBlock[SIZE - 1];
- keynr = BitmapExtBlockNr + 1;
- if (Verbose >= 2)
- printf("GetBitmapExtBlock %d -> next key %d\n", blocknr, key);
- }
-
- while (key && keynr <= blocknr) {
- GetKey(key, BitmapExtBlock);
- BitmapExtBlockNr = keynr;
- if (Verbose >= 2)
- printf("GetBitmapExtBlock %d -> get %d key %d\n",
- blocknr, keynr, key);
- key = BitmapExtBlock[SIZE - 1];
- keynr++;
- }
-
- if (key == 0 && BitmapExtBlockNr != blocknr) {
- debug0(("No bitmap extension block #%d!!!\n", keynr));
- return -97;
- }
- }
- return 0;
- }
-
- int
- GetBitmapBlock(ULONG blocknr, ULONG *buffer)
- {
- ULONG key;
-
- if (blocknr < BM_BLOCKS_PER_ROOTBLOCK) {
- key = RootBlock[SIZE - 49 + blocknr];
- if (Verbose >= 2)
- printf("GetBitmapBlock %d -> root key %d\n", blocknr, key);
- } else {
- ULONG tmp = blocknr - BM_BLOCKS_PER_ROOTBLOCK;
- ULONG bmeblocknr = tmp / BM_BLOCKS_PER_BMEBLOCK;
- ULONG offset = tmp % BM_BLOCKS_PER_BMEBLOCK;
-
- if (Verbose >= 2)
- printf("GetBitmapBlock %d -> extension block %d\n", blocknr, bmeblocknr);
-
- if ((tmp = GetBitmapExtBlock(bmeblocknr)) == 0)
- key = BitmapExtBlock[offset];
- else
- return tmp;
-
- if (Verbose >= 2)
- printf("GetBitmapBlock %d -> (ext'd) key %d\n", blocknr, key);
- }
- if (key == 0) {
- debug0(("Key for BitmapBlock #%d is 0.\n", blocknr));
- return -98;
- }
- if (GetKey(key, buffer) == 0) {
- if (CheckSum(buffer) == 0) {
- printf("Checksum of Bitmap Block #%d, key %d is bad!\n",
- blocknr, key);
- return -99;
- }
- return 0;
- }
- return Io->iotd_Req.io_Error;
- }
-
- int
- GetBit(ULONG key)
- {
- ULONG blocknr;
-
- key -= De.de_Reserved;
- blocknr = key / BitsPerBitmapBlock;
-
- if (blocknr != BitmapBlockNr) {
- if (Verbose >= 2)
- printf("GetBit %d -> BitmapBlock %d\n", key+De.de_Reserved, blocknr);
-
- if (blocknr == BitmapBlockNr + 1)
- memcpy(BitmapBlock + 1, BitmapBlock + SIZE, (SIZE - 1) * 4);
- else
- GetBitmapBlock(blocknr, BitmapBlock);
- if (GetBitmapBlock(blocknr + 1, BitmapBlock + SIZE) == 0) {
- memmove(BitmapBlock + SIZE, BitmapBlock + SIZE + 1, (SIZE - 1) * 4);
- } else {
- memset(BitmapBlock + SIZE, 0, SIZE * 4);
- debug0(("Zeroed 2nd bitmapblock.\n"));
- }
- BitmapBlockNr = blocknr;
- }
-
- return key % BitsPerBitmapBlock; /* bit offset */
- }
-
- void
- ZeroOut(int key)
- {
- debug0(("ZeroOut %d.\n", key));
- SectorsCleared++;
-
- if (GetKey(key, ZeroBlock) == 0) {
- int i;
- ULONG *p;
-
- for (i = SIZE, p = ZeroBlock; i > 0; i--, p++) {
- if (*p != 0) {
- for (; i > 0; i--, p++)
- *p = 0;
- if (!Pretend)
- PutKey(key, ZeroBlock);
- SectorsReallyCleared++;
- break;
- }
- }
- }
- }
-
- void
- ZeroTrack(int track)
- {
- char name[64];
- ULONG i;
-
- TracksDeleted++;
- i = sprintf(name, XPKDISKDIR "Unit%lx/", Fssm.fssm_Unit);
- NewName(&name[i], LowTrack + track);
- if (i = Lock(name, SHARED_LOCK)) {
- UnLock(i);
- TracksReallyDeleted++;
- printf("Delete %s.\n", name);
- if (!Pretend)
- DeleteFile(name);
- }
- }
-
- LONG
- min(LONG a, LONG b)
- {
- return a < b? a: b;
- }
-
- void
- CheckBits(int bitoffset, int numbits, ULONG key, int track)
- {
- int longindex;
- int longoffset;
- int bits;
- ULONG *p;
- char ones = 0;
- char zeros = 0;
- ULONG mask;
- int pass;
- ULONG mykey;
-
- if (Verbose >= 1) {
- printf(" Track %5d... ", track);
- }
-
- if (key == De.de_Reserved) {
- /* Pretend the reserved sectors are in use */
- zeros = 1;
- }
-
- for (pass = 0 + !XpkDisk; pass < 2; pass++) {
- longindex = bitoffset / 32;
- longoffset = bitoffset % 32;
- bits = numbits;
- mykey = key;
-
- p = BitmapBlock + 1 + longindex;
- mask = 1L << longoffset;
- debug0(("Start %08lx, track %d, pass %d, mask %08lx, bits %d\n",
- *p, track, pass, mask, bits));
-
- while (bits > 0) {
- if (*p == 0xFFFFFFFF) {
- if (pass > 0) {
- int i = min(32-1-longoffset, bits-1);
-
- debug0(("bits %d, *p %x, mykey %d: ", bits, *p, mykey));
- for (; i >= 0; i--) {
- ZeroOut(mykey + i);
- }
- }
- bits -= 32 - longoffset;
- mask = 1;
- mykey += 32 - longoffset;
- longoffset = 0;
- p++;
- debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
- ones = 1;
- } else if (*p == 0) {
- bits -= 32 - longoffset;
- mask = 1;
- mykey += 32 - longoffset;
- longoffset = 0;
- p++;
- debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
- zeros = 1;
- } else {
- if (*p & mask) {
- /* Block free */
- ones = 1;
- if (pass > 0) {
- debug0(("%08lx ", *p));
- ZeroOut(mykey);
- }
- } else {
- /* Block in use */
- zeros = 1;
- }
-
- bits--;
- mask <<= 1;
- mykey++;
- if (mask == 0) {
- longoffset = 0;
- mask = 1;
- p++;
- debug0(("Next %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
- }
- }
- }
- if (!ones || !zeros)
- break;
- }
- if (Verbose) {
- printf("%c\r", ones ? 'Z' : ' ');
- fflush(stdout);
- }
- if (XpkDisk && !zeros)
- ZeroTrack(track);
- }
-
- void
- Clear(void)
- {
- ULONG key;
- ULONG nextkey;
- ULONG track;
-
- /* First, test the boot block for file system type */
- GetKey(0, RootBlock);
- if ((RootBlock[0] & 0xFFFFFF00) != 'DOS\0') {
- printf("Not an AmigaDOS disk.\n");
- return;
- }
-
- /* Start at rootblock */
- GetKey(RootBlockKey, RootBlock);
- if (RootBlock[0] != 2 || RootBlock[SIZE-1] != ST_ROOT) {
- printf("Rootblock is not a root block.\n");
- return;
- }
- if (!CheckSum(RootBlock)) {
- printf("Rootblock checksum bad.\n");
- return;
- }
- if (RootBlock[SIZE - 50] == 0) {
- printf("Bitmap valid flag not set.\n");
- return;
- }
-
- key = De.de_Reserved;
- track = key / De.de_BlocksPerTrack;
- nextkey = (track + 1) * De.de_BlocksPerTrack;
-
- if (Verbose >= 1) {
- printf("This disk has %d tracks.\n", NumTracks);
- }
- CheckBits(GetBit(key), nextkey - key, key, track);
-
- track++;
- key = nextkey;
-
- for (; key < MaxKey; key = nextkey, track++) {
- int offset;
-
- nextkey = key + De.de_BlocksPerTrack;
- offset = GetBit(key);
- CheckBits(offset, De.de_BlocksPerTrack, key, track);
- chkabort();
- }
- }
-
- int
- OpenAll(char *devicename)
- {
- int fail = 0;
-
- {
- struct DosList *dl;
-
- if (dl = LockDosList(LDF_DEVICES | LDF_READ)) {
- if (dl = FindDosEntry(dl, devicename, LDF_DEVICES)) {
- struct FileSysStartupMsg *fssm;
- struct DosEnvec *de;
-
- fssm = BADDR(dl->dol_misc.dol_handler.dol_Startup);
- de = BADDR(fssm->fssm_Environ);
-
- Fssm = *fssm;
- Fssm.fssm_Device = (BSTR)((char *)BADDR(Fssm.fssm_Device) + 1);
- De = *de;
- HandlerPort = dl->dol_Task;
- } else {
- printf("No %s.\n", devicename);
- fail = 1;
- }
- UnLockDosList(LDF_DEVICES | LDF_READ);
- } else {
- printf("Can't LockDosList.\n");
- fail = 2;
- }
- }
- if (fail != 0)
- return fail;
-
- if (HandlerPort) {
- DoPkt(HandlerPort, ACTION_FLUSH, 0, 0, 0, 0, 0);
- DoPkt(HandlerPort, ACTION_INHIBIT, -1, 0, 0, 0, 0);
- }
-
- if (De.de_TableSize < DE_BUFMEMTYPE)
- De.de_BufMemType = MEMF_CHIP | MEMF_PUBLIC;
-
- Port = CreateMsgPort();
- if (Port == NULL)
- return 3;
-
- Io = (struct IOExtTD *)CreateExtIO(Port, sizeof(*Io));
- if (Io == NULL)
- return 4;
-
- if (fail = OpenDevice((char *)Fssm.fssm_Device, Fssm.fssm_Unit,
- (struct IORequest *)Io, Fssm.fssm_Flags)) {
- printf("Can't OpenDevice %s unit %d, error %d.\n",
- Fssm.fssm_Device, Fssm.fssm_Unit, fail);
- return 5;
- }
-
- Io->iotd_Req.io_Command = TD_CHANGENUM;
- fail = DoIO((struct IORequest *)Io);
- if (fail) {
- printf("TD_CHANGENUM: error %d\n", fail);
- return 5;
- }
- Io->iotd_Count = Io->iotd_Req.io_Actual;
-
- XpkDisk = strcmp(FilePart((char *)Fssm.fssm_Device), "xpkdisk.device") == 0;
-
- RootBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
- if (RootBlock == NULL)
- return 6;
-
- BitmapBlock = AllocMem(2 * SIZE * sizeof(ULONG), De.de_BufMemType);
- if (BitmapBlock == NULL)
- return 7;
-
- BitmapExtBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
- if (BitmapExtBlock == NULL)
- return 8;
-
- ZeroBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
- if (ZeroBlock == NULL)
- return 9;
-
- LowTrack = De.de_Surfaces * De.de_LowCyl;
- Offset = sizeof(ULONG) * SIZE * De.de_BlocksPerTrack * LowTrack;
- NumTracks = De.de_Surfaces * (De.de_HighCyl - De.de_LowCyl + 1);
- MaxKey = De.de_BlocksPerTrack * NumTracks;
- RootBlockKey = (MaxKey - 1 + De.de_Reserved) / 2;
-
- BitsPerBitmapBlock = 32 * (SIZE - 1);
-
- debug0(("Offset %x, RootBlockKey %d\n", Offset, RootBlockKey));
- debug0(("Bits/BitmapBlock %d\n", BitsPerBitmapBlock));
-
- if (De.de_BlocksPerTrack > BitsPerBitmapBlock) {
- printf(
- "What a funny disk you have! %d blocks/track is more than I can handle!\n",
- De.de_BlocksPerTrack);
- return 10;
- }
-
- return 0;
- }
-
- void
- CloseAll(void)
- {
- if (RootBlock)
- FreeMem(RootBlock, SIZE * sizeof(unsigned long));
- if (BitmapBlock)
- FreeMem(BitmapBlock, 2 * SIZE * sizeof(unsigned long));
- if (BitmapExtBlock)
- FreeMem(BitmapExtBlock, SIZE * sizeof(unsigned long));
- if (ZeroBlock)
- FreeMem(ZeroBlock, SIZE * sizeof(unsigned long));
- if (Io) {
- if (Io->iotd_Req.io_Device) {
- Io->iotd_Req.io_Command = CMD_UPDATE; /* ETD */
- DoIO((struct IORequest *)Io);
- Io->iotd_Req.io_Command = TD_MOTOR;
- Io->iotd_Req.io_Length = 0;
- DoIO((struct IORequest *)Io);
- CloseDevice((struct IORequest *)Io);
- }
- DeleteExtIO((struct IORequest *)Io);
- }
- if (Port)
- DeleteMsgPort(Port);
- if (HandlerPort) {
- DoPkt(HandlerPort, ACTION_INHIBIT, 0, 0, 0, 0, 0);
- }
-
- printf(
- "Statistics: %d (%d) sectors (really) cleared,\n"
- " %d (%d) tracks (really) deleted, \n"
- " %d free sectors total.\n",
- SectorsCleared,
- SectorsReallyCleared,
- TracksDeleted,
- TracksReallyDeleted,
- SectorsCleared + TracksDeleted * De.de_BlocksPerTrack);
- }
-
- int
- main(int argc, char **argv)
- {
- char *colon;
- int ac;
- char **av;
-
- if (DOSBase->dl_lib.lib_Version < 37) {
- printf("Sorry, requires 2.04+ (V37+)\n");
- return 20;
- }
-
- ac = argc - 1;
- av = argv + 1;
-
- while (ac > 0 && av[0][0] == '-') {
- char *a = av[0] + 1;
-
- while (a[0]) {
- switch (a[0]) {
- case 'n':
- Pretend = 1;
- printf("Pretend mode.\n");
- break;
- case 'v':
- Verbose++;
- break;
- default:
- goto usage;
- }
- a++;
- }
- ac--;
- av++;
- }
-
- if (ac < 1) {
- usage:
- printf("Usage: %s [-n] [-v] devicename\n", argv[0]);
- return 20;
- }
-
- if (colon = strchr(av[0], ':'))
- *colon = '\0';
-
- atexit(CloseAll);
-
- if (OpenAll(av[0]) == 0) {
- if (!Pretend) {
- printf("Hit return to commence clearing %s: or CTRL-C to abort: ",
- av[0]);
- fflush(stdout);
- while (!feof(stdin) && getchar() != '\n')
- /* nothing */ ;
- chkabort();
- }
- Clear();
- }
- /*CloseAll();*/
-
- return 0;
- }
-